package main.java.creatures.plant;

import static java.lang.Math.PI;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.util.Random;

import main.java.creatures.AbstractCreatureEcoSystem;
import main.java.creatures.FactoryCreatures;
import main.java.creatures.IAround;
import main.java.creatures.herbivorous.SimpleHerbivore;
import creatures.ICreature;
import creatures.IEnvironment;
/**
 * 
 *Class describe Simple plant
 * {@link AbstractCreatureEcoSystem}
 */
public class SimplePlant extends AbstractCreatureEcoSystem {

	/**
	 * When the plant is eaten, it looses health (and seeds) up to
	 * {@code MAX_DECREASE_LIFE}
	 **/
	protected int MAX_DECREASE_LIFE = 20;

	/** Default plant life **/
	public static final int DEFAULT_LIFE = 1000;

	/** Default plant color **/
	protected static final Color DEFAULT_PLANT_COLOR = Color.green;

	/** Default plant fieldOvView **/
	protected static final double DEFAULT_PLANT_FIELD_OF_VIEW = (PI * 2);

	/** Default plant direction **/
	protected static final double DEFAULT_PLANT_DIRECTION = (PI * 2);

	/**
	 * When a plant have {@code NUMBER_PLANTS_AROUND_TO_MOVE} plants around, she
	 * must move
	 **/
	protected int NUMBER_PLANTS_AROUND_TO_MOVE = 3;

	/**
	 * When it has less than {@code MIN_PLANTS_AROUND} plants around, it looses
	 * life
	 **/
	protected int MIN_PLANTS_AROUND = 2;

	/**
	 * When it has more than {@code MAX_PLANTS_AROUND} plants around, it looses
	 * life
	 **/
	protected int MAX_PLANTS_AROUND = 3;

	/** Number of plants around **/
	protected int nbSimplePlantsAround;
	
	/** Shape of plant
	 */
	protected Rectangle rectangle;

	public SimplePlant(IEnvironment environment, Point2D position,
			double direction, double speed, Color color) {
		super(environment, position);
		listClassSystem.add(SimplePlant.class);
		life = DEFAULT_LIFE;
		fieldOfView = DEFAULT_PLANT_FIELD_OF_VIEW;
		this.direction = DEFAULT_PLANT_FIELD_OF_VIEW;
		this.speed = 0;
		visionDistance = DEFAULT_VISION_DISTANCE;
		this.color = DEFAULT_PLANT_COLOR;
		super.setPosition(position);
		listSeed = FactoryCreatures.instance.createsSeeds(NUMBER_MAX_SEED,
				this.getClass());
		
		int posX = (int)position.getX() - getSize() / 2;
		int posY = (int)position.getY() - getSize() / 2;
		rectangle = new Rectangle(posX, posY, getSize(), getSize());

	}

	/**
	 * Plant have not speed.
	 * 
	 * @return always 0
	 */
	@Override
	@Deprecated
	public double getSpeed() {
		return 0;
	}

	@Override
	@Deprecated
	public void setSpeed(double speed) {
	}

	/**
	 * Plant are immobile.
	 */
	@Override
	@Deprecated
	public void setPosition(double x, double y) {
		// But we have to redefine the method to change
		// the position in the constructor
		Dimension s = environment.getSize();
		double halfSize = getSize() / 2;

		if ((x + halfSize) > s.getWidth() / 2) {
			x = -s.getWidth() / 2 + halfSize;
		} else if ((x - halfSize) < -s.getWidth() / 2) {
			x = s.getWidth() / 2 - halfSize;
		}

		if ((y + halfSize) > s.getHeight() / 2) {
			y = -s.getHeight() / 2 + halfSize;
		} else if ((y - halfSize) < -s.getHeight() / 2) {
			y = s.getHeight() / 2 - halfSize;
		}

		this.position = new Point2D.Double(x, y);
	}

	/**
	 * Plant are immobile.
	 */
	@Override
	@Deprecated
	public void setPosition(Point2D position) {
	}

	/**
	 * We can't change the direction Always 2*PI
	 */
	@Override
	@Deprecated
	public void setDirection(double direction) {
	}

	@Override
	public int getSize() {
		return (int) (life * 0.02);
	}

	public Rectangle getRectangle() {
		return rectangle;
	}
	
	@Override
	protected void move(double incX, double incY) {
		super.move(incX, incY);
		initRect();
	}

	/**
	 * Initialize the rectangle
	 * 
	 */
	private void initRect() {
		int posX = (int)position.getX() - getSize() / 2;
		int posY = (int)position.getY() - getSize() / 2;
		rectangle.setBounds(posX, posY, getSize(), getSize());
	}
	
	@Override
	public void act() {

		nbSimplePlantsAround = 0;
		Iterable<ICreature> creatures = creaturesAround(this);

		for (ICreature iCreature : creatures) {
			((IAround) iCreature).isVisitedBy(this);
		}

		if (nbSimplePlantsAround == NUMBER_PLANTS_AROUND_TO_MOVE) {
			Random rand = new Random();
			move(rand.nextDouble() * 5, rand.nextDouble() * 5); // [0;5]
		} else if (nbSimplePlantsAround < MIN_PLANTS_AROUND
				|| nbSimplePlantsAround > MAX_PLANTS_AROUND) {
			life--;
			verifyLife();
		} 
		rectangle.setSize(getSize(), getSize());
		
	}
	
	@Override
	public void isVisitedBy(final SimpleHerbivore h) {
		h.visit(this);

	}

	@Override
	public void isVisitedBy(final SimplePlant p) {
		p.visit(this);
		
		//verify if plants are not layered
		if(p.getRectangle().intersects(rectangle)) {
			Random rand = new Random();
			p.move(rand.nextDouble() * 2 - 1, rand.nextDouble() * 2 - 1);
		}
		
	}

	@Override
	public void visit(final SimpleHerbivore h) {
	}

	@Override
	public void visit(final SimplePlant p) {
		nbSimplePlantsAround++;
	}

	/**
	 * 
	 * Decrease Plant life
	 * {@link #MAX_DECREASE_LIFE}
	 * @return losted life
	 */
	public final int decreaseLife() {
		int eat = new Random().nextInt(MAX_DECREASE_LIFE) + 1; // [1;MAX_DECREASE_LIFE]
		life -= eat;
		verifyLife();
		return eat;
	}

	@Override
	public void paint(final Graphics2D g2) {
		
		g2.setColor(color);		
		g2.fill(rectangle);
		
	}

}
